package edu.hawaii.senin.iclouds.plotting;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * Parses log and generates data for plotting.
 *
 * @author Pavel Senin.
 *
 */
public class MainGeneralParser {

  /**
   * Parses the log and reports data for plotting.
   *
   * @param args species of interest.
   */
  public static void main(String[] args) {
    if (0 == args.length) {
      System.out.println("iClouds log file parser");
      System.out.println("-----------------------");
      System.out.println("please refer to the documentation for the usage\n "
          + "typically you need to provide a XML config file.");
    }
    else {

      String configFileName = args[0];

      try {

        // at first parsing species of interest

        Collection<Callable<String>> assignments = parseAssignment(configFileName);

        ExecutorService e = Executors.newFixedThreadPool(1);

        CompletionService<String> ecs = new ExecutorCompletionService<String>(e);

        for (Callable<String> assignment : assignments) {
          ecs.submit(assignment);
        }

        int n = assignments.size();

        for (int i = 0; i < n; ++i) {
          String str = ecs.take().get();
          System.out.println(str);
        }

      }
      catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      catch (JDOMException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

    }

  }

  /**
   * Implements callable task for parsing log files.
   *
   * @param configFileName the configuration file name to parse.
   * @return the Future results that are managable by for Callable threadpool.
   * @throws JDOMException if error while reading configuration.
   * @throws IOException if something wrong with IO.
   */
  private static Collection<Callable<String>> parseAssignment(String configFileName)
                                                              throws JDOMException, IOException {

    // fixing up assignments
    Collection<Callable<String>> res = new ArrayList<Callable<String>>();

    SAXBuilder builder = new SAXBuilder();
    BufferedReader reader = new BufferedReader(new FileReader(new File(configFileName)));
    Document config = builder.build(reader);
    Element root = config.getRootElement();
    Iterator itr = root.getChildren().iterator();
    while (itr.hasNext()) {
      Element e = (Element) itr.next();
      String kind = e.getAttributeValue("task");
      if ("4Dplot".equalsIgnoreCase(kind)) {
        res.add(new GeneralLogParserTask(e, getSpeciesOfInterest(e.getAttributeValue("species"))));
      }
      else if ("HDO/H2O".equalsIgnoreCase(kind)) {
        res
          .add(new GeneralHDOH2OParserTask(e,
                                            getSpeciesOfInterest(e.getAttributeValue("species"))));
      }
      else if ("evolution".equalsIgnoreCase(kind) || "cascade".equalsIgnoreCase(kind)) {
        res.add(new EvolutionLogParserTask(e, getSpeciesOfInterest(e.getAttributeValue("species")),
            kind));
      }
      else if ("Hfractions".equalsIgnoreCase(kind)) {
        res
          .add(new FractionHLogParserTask(e, getSpeciesOfInterest(e.getAttributeValue("species"))));
      }
      else if ("Dfractions".equalsIgnoreCase(kind)) {
        res
          .add(new FractionDLogParserTask(e, getSpeciesOfInterest(e.getAttributeValue("species"))));
      }
    }

    reader.close();

    return res;
  }

  /**
   * Parses a file to extract species of interest.
   * @param fileName the file name.
   * @return species of interest as the collection.
   * @throws JDOMException when XML found inappropriate.
   * @throws IOException when IO error encountered.
   */
  private static List<String> getSpeciesOfInterest(String fileName) throws JDOMException,
      IOException {
    SAXBuilder builder = new SAXBuilder();
    BufferedReader reader = new BufferedReader(new FileReader(new File(fileName)));
    Document config = builder.build(reader);
    Element root = config.getRootElement();
    // get list of species of interest
    List<String> speciesOfInterest = new ArrayList<String>();
    List species = root.getChildren();
    Iterator itr = species.iterator();
    while (itr.hasNext()) {
      Element el = (Element) itr.next();
      String specieName = el.getValue();
      speciesOfInterest.add(specieName);
    }
    reader.close();
    return speciesOfInterest;
  }

}
